﻿using RotovapPlatform.Domain.Equipment.Device.OilBath.Dto;
using RotovapPlatform.Domain.Equipment.Interfaces.Base;
using RotovapPlatform.Domain.Equipment.Interfaces.Communication;
using RotovapPlatform.Domain.Common.Exceptions;
using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Common;

namespace RotovapPlatform.Infrastructure.Equipment.Devices.OilBath
{
	public class OilBathDrive : IOilBathBase
	{
		private readonly ISerialServerManager _serverManager;
		private readonly ILogger<OilBathDrive> _logger;
		private readonly int _port;
		private readonly byte _slaveId;

		public OilBathDrive(
			ISerialServerManager serverManager,
			int port,
			byte slaveId,
			string name,
			ILogger<OilBathDrive> logger)
		{
			_serverManager = serverManager;
			_port = port;
			_slaveId = slaveId;
			_logger = logger;
			Name = name;
			EquipmentId = $"OilBath_{port}_{slaveId}";
		}

		public string Name { get; }
		public string EquipmentId { get; }

		public async Task<OilBathStatus> GetOilBathStatusAsync()
		{
			try
			{
				// 读取从0x2000开始的6个寄存器
				var registers = await _serverManager.ReadHoldingRegistersAsync(
					_port,
					_slaveId,
					0x2000,  // 起始地址
					6        // 读取长度
				);

				// 解析状态字节 (0x2001)
				ushort statusByte = registers[1];

				var status = new OilBathStatus
				{
					CurrentTemperaturePV = registers[0] / 10.0,  // 0x2000 PV
					Out1 = (statusByte & 0x0001) != 0,          // OUT1
					Out2 = (statusByte & 0x0002) != 0,          // OUT2
					AL1 = (statusByte & 0x0004) != 0,           // AL1
					AL2 = (statusByte & 0x0008) != 0,           // AL2
					AT = (statusByte & 0x0010) != 0,            // AT
					Stop = (statusByte & 0x0080) != 0,          // STOP
					SetTemperatureSV = registers[3] / 10.0,     // 0x2003 SV
					Mode = registers[5]                          // 0x2005 A-M
				};

				//// 记录报警状态
				//if (status.AL1 || status.AL2)
				//{
				//	_logger.LogWarning("油浴锅 {Name} 存在报警: AL1={AL1}, AL2={AL2}",
				//		Name, status.AL1, status.AL2);
				//}

				return status;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "读取油浴锅 {Name} 状态失败", Name);
				throw new CommunicationException($"读取油浴锅状态失败: {ex.Message}", ex);
			}
		}

		public async Task<OperationResult> SetTemperatureAsync(double temperature)
		{
			try
			{
				var value = (ushort)(temperature * 10);  // 温度值需要乘以10
				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x2003,  // SV地址
					new[] { value }
				);
				_logger.LogInformation("油浴锅 {Name} 设置温度为: {Temperature}℃", Name, temperature);
				return OperationResult.Ok($"油浴锅 {Name} 温度设置为 {temperature}℃");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置油浴锅 {Name} 温度失败, 目标温度: {Temperature}℃", Name, temperature);
				return OperationResult.Fail($"设置油浴锅温度失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> SetRunningStatusAsync(int status)
		{
			try
			{
				if (status < 0 || status > 3)
				{
					return OperationResult.Fail("运行状态必须在0-3之间");
				}

				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x2004,  // RSA地址
					new[] { (ushort)status }
				);

				string statusText = status switch
				{
					0 => "运行",
					1 => "暂停",
					2 => "停止",
					3 => "自整定",
					_ => "未知"
				};

				_logger.LogInformation("油浴锅 {Name} 设置运行状态为: {Status}", Name, statusText);
				return OperationResult.Ok($"油浴锅 {Name} 设置运行状态为 {statusText} 成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置油浴锅 {Name} 运行状态失败, 状态值: {Status}", Name, status);
				return OperationResult.Fail($"设置油浴锅运行状态失败: {ex.Message}");
			}
		}

		public async Task<OperationResult> SetControlModeAsync(int mode)
		{
			try
			{
				if (mode < 0 || mode > 2)
				{
					return OperationResult.Fail("控制模式必须在0-2之间");
				}

				await _serverManager.WriteHoldingRegistersAsync(
					_port,
					_slaveId,
					0x2005,  // A-M地址
					new[] { (ushort)mode }
				);

				string modeText = mode switch
				{
					0 => "程序控制",
					1 => "手动控制",
					2 => "手动/自动模式切换",
					_ => "未知"
				};

				_logger.LogInformation("油浴锅 {Name} 设置控制模式为: {Mode}", Name, modeText);
				return OperationResult.Ok($"油浴锅 {Name} 设置控制模式为 {modeText} 成功");
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "设置油浴锅 {Name} 控制模式失败, 模式值: {Mode}", Name, mode);
				return OperationResult.Fail($"设置油浴锅控制模式失败: {ex.Message}");
			}
		}
	}
}
